package javagamecontroller.components.joystick;

import com.javagamecontroller.R;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.util.Log;
import android.content.res.Resources;


/**
 * A class containing the knob of a joystick.
 * 
 * @author Ben Schwab
 * 
 */
public class Knob {

    private static final int VIBRATE_TIME = 5;
    private BitmapDrawable myKnobImage;
    private int myKnobSize;
    private Rect myBounds;
    private boolean myIsDragging = false;
    private Point myBoundCenter;
    private double myAngle;
    private double myMagnitude;
    private int myPadSize;
    private JoyStick myJoyStick;

    /**
     * Create a new knob
     * @param resource the resource of the knob image
     * @param center center point of knob
     * @param size of the knob
     * @param padSize size of the pad
     * @param parent the joystick that holds the knob
     */
    public Knob (Resources resource, Point center, int size, int padSize, JoyStick parent) {
        myPadSize = padSize;
        myJoyStick = parent;
        myKnobImage =
                new BitmapDrawable(resource, BitmapFactory.decodeResource(resource,
                                                                          R.drawable.thumpad));
        myKnobSize = size;
        myBoundCenter = center;
        setCenter(center);

    }

    protected void draw (Canvas c) {
        myKnobImage.draw(c);

    }

    protected boolean containsPoint (Point p) {
        return myBounds.contains(p.x, p.y);
    }

    protected void setCenter (Point center) {

        int dy = center.y - myBoundCenter.y;
        int dx = center.x - myBoundCenter.x;
        if (dx == 0) {
            myAngle = 0;
        }
        else {
            myAngle = -Math.atan((double) dy / dx) * (360.0 / (2 * Math.PI));
            if (dy < 0 && dx < 0) {
                myAngle += 180;
            }
            else if (dy > 0 && dx > 0) {
                myAngle += 360;
            }
            else if (dy > 0 && dx < 0) {
                myAngle = 180 + myAngle;
            }

        }
        myMagnitude = Math.pow(Math.pow(dx, 2) + Math.pow(dy, 2), .5);
        if (Math.pow(Math.pow(dx, 2) + Math.pow(dy, 2), .5) > myPadSize / 2) {
            myMagnitude = myPadSize / 2;
            myJoyStick.vibrate(VIBRATE_TIME);
            center.x = myBoundCenter.x + (int) (Math.cos(Math.toRadians(myAngle)) * myPadSize / 2);
            center.y = myBoundCenter.y - (int) (Math.sin(Math.toRadians(myAngle)) * myPadSize / 2);
            Log.e("mag", "" + center.x + " " + center.y);
        }
        myBounds =
                new Rect(center.x - myKnobSize / 2, center.y - myKnobSize / 2, center.x + myKnobSize / 2,
                         center.y + myKnobSize / 2);
        myKnobImage.setBounds(myBounds);

    }
    /**
     * 
     * @param size new size of the knob
     */
    public void setSize (int size) {
        myKnobSize = size;
    }
    /**
     * 
     * @return the size of the knob
     */
    public int getSize () {
        return myKnobSize;
    }
    /**
     * 
     * @param point to check if knob contains
     */
    public void checkCapture (Point point) {
        if (myBounds.contains(point.x, point.y)) {
            myIsDragging = true;
        }
    }

    /**
     * release the knob returning it to the center
     * 
     * @param point
     */
    public void release () {
        myIsDragging = false;
        setCenter(myBoundCenter);

    }

    protected void dragKnob (Point point) {
        if (myIsDragging) {
            setCenter(point);
        }
    }

    /**
     * Get the angle of the joystick in degrees.
     * 
     * @return
     */
    public double getAngle () {
        return myAngle;
    }

    /**
     * Returns the magnitude of the joystick from 0 to 1.
     * 
     * @return the relative magnitude of the joystick
     */
    public double getMagnitude () {
        return myMagnitude / (myPadSize / 2);
    }

}
